package com.cx.webpay.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.UUID;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;

import com.cx.webpay.model.FileVo;


/**
 * 文件压缩工具
 */
public class ZipUtil {

	/**
	 * 文件减压缩保存
	 * @param file
	 *            文件
	 * @param fileListInfo
	 *            文件信息
	 * @throws IOException
	 */
	@SuppressWarnings("resource")
	public static void unZipFile(File file, List<FileVo> fileListInfo, String projId) throws IOException {
		FileVo fileInfo = null;
		String originalName = file.getName();
		if (-1 == originalName.indexOf(".zip")) {
			fileListInfo.add(fileInfo);
			return;
		} // 不解压文件
		String tempFileDirPath = FileCommonConstant.FILE_SAVE_FILE_DEFAULT;
		String teamFileDirPath = projId + "/" + DateUtil.getLocalDateString();
		File tempFileDir = new File(tempFileDirPath + teamFileDirPath);
		if (!tempFileDir.exists()) {
			tempFileDir.mkdirs();
		}
		ZipEntry zipEntry = null;
		File entryFile = null;
		int count = 0;
		byte[] buffer = new byte[1024];
		BufferedOutputStream bos = null;
		FileOutputStream fos = null;
		BufferedInputStream bis = null;
		ZipFile zip = null;
		// 转为zipfile
		zip = new ZipFile(file, Charset.forName("GBK"));
		@SuppressWarnings("unchecked")
		Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>) zip.entries();
		while (entries.hasMoreElements()) {
			try {
				zipEntry = entries.nextElement();
				String ext = "";
				String fileName = zipEntry.getName();
				fileName = -1 < fileName.indexOf("/") ? fileName.substring(fileName.lastIndexOf("/") + 1) : fileName;
				long fileSize = zipEntry.getSize() / 1024;
				String fileId = UUID.randomUUID().toString().replaceAll("-", "");
				try {
					ext = FilenameUtils.getExtension(fileName);
				} catch (Exception e) {
					e.printStackTrace();
				} // 无扩展名
				if (StringUtils.isEmpty(ext))
					continue;// 无后缀名不储存
				String newChildFileName = fileId + "." + ext;
				String newChildFilePath = tempFileDirPath + teamFileDirPath + "/" + newChildFileName;
				entryFile = new File(newChildFilePath);
				if (entryFile.exists())
					entryFile.delete();
				entryFile.createNewFile();
				fos = new FileOutputStream(entryFile);
				bis = new BufferedInputStream(zip.getInputStream(zipEntry));
				bos = new BufferedOutputStream(new FileOutputStream(entryFile));
				fileInfo = new FileVo();
				fileInfo.setExt(ext);
				fileInfo.setFileId(fileId);
				fileInfo.setFileName(fileName);
				fileInfo.setPath(teamFileDirPath + "/" + newChildFileName);
				fileInfo.setSize(String.valueOf(fileSize));
				fileInfo.setDoType(FileExecuteEnum.FILE_ORIGIN.getCode() + "");
				fileInfo.setParentId("0");// 原文件
				while ((count = bis.read(buffer, 0, 1024)) != -1) {
					bos.write(buffer, 0, count);
				}
				bos.flush();
				fileListInfo.add(fileInfo);
			} finally {
				if (bos != null)bos.close();
				if (bis != null)bis.close();
				if (fos != null)fos.close();
			}
		}
	}

	/**
	 * 解压rar格式压缩包。
	 * @param sourceRar
	 *            压缩资源
	 * @param //destDir
	 *            解压资源
	 * @throws Exception
	 */
	@SuppressWarnings("unused")
	public static boolean unRARFile(String sourceRar) throws Exception {
		boolean flag = false;
		try {
			if (File.separator.equals("/") && (sourceRar.endsWith(".rar") || sourceRar.endsWith(".RAR"))) {
				Process p = Runtime.getRuntime().exec("unrar e " + sourceRar);
				flag = true;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return flag;
	}

	/**
	 * 获取文件信息
	 * @param dir
	 * @return
	 * @throws IOException
	 */
	public static List<FileVo> getFileInfoFromDir(String dir,FileExecuteEnum enums) throws IOException {
		List<FileVo> list = new ArrayList<FileVo>();
		File parentFile = new File(dir);
		if (parentFile.isDirectory()) {
			File[] files = parentFile.listFiles();
			for (File file : files) {
				if (file.isDirectory() && file.length() > 0) {
					getFileInfoFromDir(file.getParent(),enums);
				} else if (file.isFile() && file.length() > 0) {
					list.add(getFileInfo(file,enums));
				}
			}
		}
		return list;
	}

	// 文件重命名
	public static FileVo getFileInfo(File file, FileExecuteEnum enums) throws IOException {
		FileVo fileInfo = new FileVo();
		String filename = file.getName();
		String fileId = DateUtil.uuidRandom();
		String ext = FilenameUtils.getExtension(filename);
		String path = file.getParent() + "/" + fileId + "." + ext;
		File newFile = new File(path);
		fileInfo.setDoType(enums.getCode() + "");
		fileInfo.setExt(ext);
		fileInfo.setFileId(fileId);
		fileInfo.setFileName(filename);
		fileInfo.setParentId("0");
		fileInfo.setSize(file.length() + "");
		fileInfo.setPath(path);
		file.renameTo(newFile);
		return fileInfo;
	}

	/**
	 * 
	 * @param zipSavePath
	 *            压缩的目的地址
	 * @param zipOut
	 * @param srcFile
	 *            被压缩的文件信息
	 * @param path
	 *            在zip中的相对路径
	 * @throws IOException
	 */
	private static void handlerFile(String zipSavePath, ZipOutputStream zipOut, File srcFile, String path)
			throws IOException {
		if (!"".equals(path) && !path.endsWith(File.separator)) {
			path += File.separator;
		}
		if (srcFile.isDirectory()) {
			File[] files = srcFile.listFiles();
			if (files.length == 0) {
				zipOut.putNextEntry(new ZipEntry(path + srcFile.getName() + File.separator));
				zipOut.closeEntry();
			} else {
				for (File file : files) {
					handlerFile(zipSavePath, zipOut, file, path + srcFile.getName());
				}
			}
		} else {
			byte[] buffer = new byte[1024];
			InputStream in = new FileInputStream(srcFile);
			zipOut.putNextEntry(new ZipEntry(path + srcFile.getName()));
			int len = 0;
			while ((len = in.read(buffer)) > 0) {
				zipOut.write(buffer, 0, len);
			}
			in.close();
			zipOut.closeEntry();
		}
	}

	/**
	 * 压缩文件 为zip
	 * @param zipSavePath
	 * @param srcFiles
	 * @throws Exception
	 */
	public static void zipFile(String zipSavePath, List<File> srcFiles) throws Exception {
		try {
			if (zipSavePath.endsWith(".zip") || zipSavePath.endsWith(".ZIP")) {
				ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(new File(zipSavePath)));
				srcFiles.stream().forEach(file -> {
					try {
						handlerFile(zipSavePath, zipOut, file, "");
					} catch (IOException e) {
						e.printStackTrace();
						throw new RuntimeException("运行异常");
					}
				});
				zipOut.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}
